﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WorkflowCore.Interface;
using WorkflowCore.Models;
using WorkflowCore.Primitives;
using WorkflowCore.Service.Dto.Fundamentals;
using WorkflowCore.Service.Persisted;

namespace WorkflowCore.Service.Steps
{
    /// <summary>
    /// 角色审批
    /// </summary>
    public class RoleForeach : ContainerStepBody
    {
        private readonly WorkflowCoreDbcontext workflowCoreDbcontext;
        private readonly GetWorkflowCoreUserData getWorkflowCoreUserData;

        public RoleForeach(WorkflowCoreDbcontext workflowCoreDbcontext, GetWorkflowCoreUserData getWorkflowCoreUserData)
        {
            this.workflowCoreDbcontext = workflowCoreDbcontext;
            this.getWorkflowCoreUserData = getWorkflowCoreUserData;
        }

        //代表角色ID
        public string Collection {  get; set; }
        //是否可并行
        public bool Runparallel {  get; set; }

        public override ExecutionResult Run(IStepExecutionContext context)
        {
            List<PersonNode> Users = getWorkflowCoreUserData.ShoWorkflowCoreUserData();
            var roleIdList = JsonConvert.DeserializeObject<List<long>>(Collection)!;

            // 待审批的人员ID
            var userIdList = Users.Where(p => roleIdList.Contains(p.RoleId)).Select(p => p.UserId);
            if (context.PersistenceData == null)
            {
                // 变更业务流程实例信息
                var instance =
                    workflowCoreDbcontext.persistedWorkflowInstance
                        .FirstOrDefault(p => p.WorkflowInstanceId == context.Workflow.Id);
                var userNames = string.Join(',', Users.Where(p => userIdList.Contains(p.UserId)).Select(p => p.UserName));
                instance.CurrentAuditUserIds = string.Join(',', userIdList);
                instance.CurrentAuditUsers = userNames;
                instance.CurrentStepId = context.Step.ExternalId;
                instance.CurrentStepName = context.Step.Name;
                workflowCoreDbcontext.SaveChanges();

                var values = userIdList.Cast<object>().ToList();
                if (!values.Any())
                {
                    return ExecutionResult.Next();
                }

                if (Runparallel)
                {
                    return ExecutionResult.Branch(new List<object>(values),
                        new IteratorPersistenceData { ChildrenActive = true });
                }
                else
                {
                    return ExecutionResult.Branch(new List<object>(new object[] { values.ElementAt(0) }),
                        new IteratorPersistenceData { ChildrenActive = true });
                }
            }

            if (context.PersistenceData is IteratorPersistenceData persistenceData &&
                persistenceData?.ChildrenActive == true)
            {
                if (context.Workflow.IsBranchComplete(context.ExecutionPointer.Id))
                {
                    if (!Runparallel)
                    {
                        var values = userIdList.Cast<object>();
                        persistenceData.Index++;
                        if (persistenceData.Index < values.Count())
                        {
                            return ExecutionResult.Branch(
                                new List<object>(new object[] { values.ElementAt(persistenceData.Index) }), persistenceData);
                        }
                    }

                    return ExecutionResult.Next();
                }

                return ExecutionResult.Persist(persistenceData);
            }

            if (context.PersistenceData is ControlPersistenceData controlPersistenceData &&
                controlPersistenceData?.ChildrenActive == true)
            {
                if (context.Workflow.IsBranchComplete(context.ExecutionPointer.Id))
                {
                    return ExecutionResult.Next();
                }
            }

            return ExecutionResult.Persist(context.PersistenceData);
        }
    }
}
